/**
* 版权声明：厦门睿商网络科技有限公司 版权所有 违者必究
* 日    期：2021-01-08
*/
package com.rzico.market.service;

import com.alibaba.fastjson.JSON;
import com.rzico.account.entity.*;
import com.rzico.account.model.Attach;
import com.rzico.account.service.PhonePaymentService;
import com.rzico.account.service.PhoneRefundsService;
import com.rzico.base.BaseMapper;
import com.rzico.base.impl.BaseServiceImpl;
import com.rzico.basics.entity.*;
import com.rzico.basics.service.EnterpriseService;
import com.rzico.basics.service.MemberService;
import com.rzico.basics.service.MsgService;
import com.rzico.core.entity.SysPlugin;
import com.rzico.core.entity.SysUser;
import com.rzico.core.service.SysPluginService;
import com.rzico.core.service.SysSequenceService;
import com.rzico.core.service.SysUserService;
import com.rzico.exception.CustomException;
import com.rzico.market.entity.*;
import com.rzico.market.enumx.PhoneOrderStatusEnum;
import com.rzico.market.model.PhoneOrderVo;
import com.rzico.market.plugin.phoneBill.DxPhonePlugin;
import com.rzico.util.RedisHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.rzico.market.mapper.PhoneOrderMapper;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <pre>
 * 豆讯话费订单管理业务类
 * </pre>
 *
 * @author Rzico Boot
 * @version 1.0
 */
@Service
@Slf4j
public class PhoneOrderService extends BaseServiceImpl<PhoneOrder, String> {

    @Autowired
    private PhoneOrderMapper phoneOrderMapper;

    @Override
    public BaseMapper<PhoneOrder, String> getMapper() {
        return phoneOrderMapper;
    }

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    protected SysPluginService sysPluginService;

    @Autowired
    private EnterpriseService enterpriseService;

    @Autowired
    public DxPhonePlugin dxPhonePlugin;

    @Autowired @Lazy
    private MsgService msgService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private PhoneOrderItemService phoneOrderItemService;

    @Autowired
    private PhonePaymentService phonePaymentService;

    @Autowired
    private PhoneOrderLogService phoneOrderLogService;

    @Autowired
    private PhoneProductService phoneProductService;

    @Autowired
    private RedisHandler redisHandler;

    @Autowired
    private SysSequenceService sysSequenceService;

    @Autowired
    private PhoneRefundsService phoneRefundsService;


    /**
     * 查询话费订单信息
     * @param params
     * @return
     */
    public List<PhoneOrderVo> selectPhoneOrderList(Map<String, Object> params){
        return phoneOrderMapper.selectPhoneOrderList(params);
    }

    /**
     * 创建订单
     * @param phoneOrder
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int insertOrder(PhoneOrder phoneOrder){
        phoneOrder.setCreateDate(new Date());
        phoneOrder.setOrderStatus(0);
        phoneOrder.setPaymentStatus(0);
        phoneOrder.setDeleted(false);
        //是否第一单
        phoneOrder.setIsFirst(false);
        initPhoneOrder(phoneOrder);

        //计算订单金额
        BigDecimal amountPayable = phoneOrder.calculateAmountPayable();
        BigDecimal subPrice = phoneOrder.calculateSubPrice();
        BigDecimal subQuantity = phoneOrder.calculateSubQuantity();


        Member member = memberService.findById(phoneOrder.getMemberId());
        if (amountPayable.subtract(phoneOrder.getAmountPaid()).compareTo(BigDecimal.ZERO)<0) {
            throw new CustomException("不能超额付款");
        }


        phoneOrder.setSubPrice(subPrice);
        phoneOrder.setSubQuantity(subQuantity);
        phoneOrder.setAmountPayable(amountPayable);
        if (phoneOrder.getAmountPaid().compareTo(phoneOrder.getAmountPayable())>=0) {
            phoneOrder.setOrderStatus(1);
            phoneOrder.setPaymentStatus(1);
        }

        Integer rw = insertUseGeneratedKeys(phoneOrder);

        List<PhoneOrderItem> itemList = new ArrayList<>();
        for (PhoneOrderItem phoneOrderItem : phoneOrder.getItemList()){
            initPhoneOrderItem(phoneOrderItem);
            phoneOrderItem.setOrderId(phoneOrder.getId());
            itemList.add(phoneOrderItem);
        }
        phoneOrder.setItemList(itemList);


        PhoneOrderLog phoneOrderLog = new PhoneOrderLog();
        phoneOrderLog.setType(PhoneOrderStatusEnum.ORDER_LOG_TYPE_CREATE.getId());
        phoneOrderLog.setContent("订单已创建");
        phoneOrderLog.setCreateDate(new Date());
        phoneOrderLog.setOrderId(phoneOrder.getId());
        phoneOrderLogService.insertUseGeneratedKeys(phoneOrderLog);

        member.setAmount(member.getAmount().add(phoneOrder.getAmountPayable()));
        member.setPoint(null);
        member.setFreezePoint(null);
        member.setBalance(null);
        member.setFreezeBalance(null);
        member.setMatchPoint(null);

        memberService.updateByPrimaryKeySelective(member);

        try {

            Map<String,Object> content = new HashMap<>();
            content.put("title","订单已创建");
            content.put("itemList",phoneOrder.getItemList());
            content.put("sn",phoneOrder.getSn());
            content.put("id",phoneOrder.getId());
            msgService.sendNotity(member,"msg-order","超时30分钟未付款,订单将自动关闭", JSON.toJSONString(content),null);

        } catch (Exception e) {
            log.error(e.getMessage());
        }

        return rw;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertUseGeneratedKeys(PhoneOrder phoneOrder) {
        phoneOrder.setOrderDate(DateUtils.truncate(phoneOrder.getOrderDate(),Calendar.DATE));
        int affectCount = super.insertUseGeneratedKeys(phoneOrder);
        if (affectCount > 0){
            for (PhoneOrderItem phoneOrderItem : phoneOrder.getItemList()){
                phoneOrderItem.setOrderId(phoneOrder.getId());
            }
            phoneOrderItemService.insertUseGeneratedKeyList(phoneOrder.getItemList());
        }
        return affectCount;
    }

    /**
     * 构建订单
     * @param phoneOrder
     */
    private void initPhoneOrder(PhoneOrder phoneOrder){
        if (phoneOrder.getIsFirst()==null) {
            phoneOrder.setIsFirst(false);
        }
        //若空，默认0线上结算
        if (null == phoneOrder.getAmountPaid()){
            phoneOrder.setAmountPaid(BigDecimal.ZERO);
        }
        if (null == phoneOrder.getAmountPayable()){
            phoneOrder.setAmountPayable(BigDecimal.ZERO);
        }
        if (null == phoneOrder.getDiscount()){
            phoneOrder.setDiscount(BigDecimal.ZERO);
        }
        if (null == phoneOrder.getSubPrice()){
            phoneOrder.setSubPrice(BigDecimal.ZERO);
        }
        if (null == phoneOrder.getSubQuantity()){
            phoneOrder.setSubQuantity(BigDecimal.ZERO);
        }
        if (null == phoneOrder.getMemberId()){
            phoneOrder.setMemberId(0L);
        }
        if (null == phoneOrder.getOrderMethod()){
            phoneOrder.setOrderMethod(0);
        }
        if (null == phoneOrder.getOrderStatus()){
            phoneOrder.setOrderStatus(0);
        }
        if (null == phoneOrder.getPaymentStatus()){
            phoneOrder.setPaymentStatus(0);
        }
        if (null == phoneOrder.getOrderDate()){
            phoneOrder.setOrderDate(DateUtils.truncate(new Date(),Calendar.DATE));
        } else {
            phoneOrder.setOrderDate(DateUtils.truncate(phoneOrder.getOrderDate(),Calendar.DATE));
        }
    }

    /**
     * 构建话费订单项
     * @param phoneOrderItem
     */
    private void initPhoneOrderItem(PhoneOrderItem phoneOrderItem){
        PhoneProduct phoneProduct = phoneProductService.selectByPrimaryKey(phoneOrderItem.getProductId());
        phoneOrderItem.setCreateDate(new Date());
        phoneOrderItem.setName(phoneProduct.getName());
        phoneOrderItem.setSn(phoneProduct.getSn());
        phoneOrderItem.setCost(phoneProduct.getCost());
        phoneOrderItem.setThumbnail(phoneProduct.getThumbnail());
        //商品库存-1
        Map<String,Object> data = new HashMap<>();
        data.put("id", phoneOrderItem.getProductId());
        data.put("value", BigDecimal.ONE);
        phoneProductService.decStock(data);
    }

    /**
     * 生成付款单
     * @param phoneOrder
     * @param sn
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public PhonePayment payment(PhoneOrder phoneOrder, String sn) {
        PhonePayment phonePayment = new PhonePayment();
        phonePayment.setCreateDate(new Date());
        phonePayment.setDeleted(false);
        phonePayment.setSn(sn);
        phonePayment.setAmount(phoneOrder.getAmountPayable().subtract(phoneOrder.getAmountPaid()));
        phonePayment.setRefund(BigDecimal.ZERO);
        Attach attach = new Attach();
        attach.setId(String.valueOf(phoneOrder.getId()));
        attach.setCode("9999");
        attach.setQueue("queue.phoneOrder.phonePayment");
        attach.setDescription(phoneOrder.getTitle());
        phonePayment.setAttach(JSON.toJSONString(attach));
        phonePayment.setEnterpriseId(phoneOrder.getEnterpriseId());
        phonePayment.setMemberId(phoneOrder.getMemberId());
        phonePayment.setExpire(DateUtils.addMinutes(new Date(),30));
        phonePayment.setStatus(Payment.STATUS_WAITING);
        phonePayment.setType(Payment.TYPE_ORDER);
        phonePayment.setMethod(Payment.METHOD_ONLINE);
        phonePayment.setMemo("订单-"+phoneOrder.getTitle());
        phonePayment.setWay(1);
        phonePayment.setOrderId(phoneOrder.getId());
        phonePayment.setOrderSn(phoneOrder.getSn());
        phonePayment.setFee(BigDecimal.ZERO);

        int tw = phonePaymentService.insertUseGeneratedKeys(phonePayment);
        if (0 < tw) {
            phoneOrder.setModifyDate(new Date());
            phoneOrder.setAmountPaid(phoneOrder.getAmountPayable());
            super.updateByPrimaryKey(phoneOrder);
        }
        return phonePayment;

    }

    /**
     * 检查豆讯话费充值结果
     * @param list
     */
    public void phoneOrderCheck(List<PhoneOrder> list){
        Long enterpriseId = list.get(0).getEnterpriseId();
        Enterprise enterprise = enterpriseService.findById(enterpriseId);
        SysPlugin sysplugin = sysPluginService.findByPlugin(enterprise.getMchId(), "dxPhonePlugin");
        dxPhonePlugin.setPlugin(sysplugin, enterprise.getMchId());
        for (PhoneOrder po : list) {
            Map<String, Object> param = new HashMap<String, Object>();
            param.put("orderIds", po.getSn());
            try {
                Map<String, Object> result = dxPhonePlugin.orderQuery(sysplugin, param);
                if ("0000".equals(result.get("result").toString())) {
                    po.setModifyDate(new Date());
                    po.setResult(true);
                    po.setOrderStatus(PhoneOrderStatusEnum.ORDER_STATUS_COMPLETE.getId());
                    super.updateByPrimaryKeySelective(po);
                } else {
                    if (null != po.getResult()) {
                        continue;
                    }
                    po.setModifyDate(new Date());
                    po.setResult(false);
                    super.updateByPrimaryKeySelective(po);
                    insertRefunds(po);
                    //商品库存+1
                    Map<String,Object> data = new HashMap<>();
                    List<PhoneOrderItem> phoneOrderItemList = phoneOrderItemService.getItemList(po.getId());
                    if (0 < phoneOrderItemList.size()) {
                        data.put("id", phoneOrderItemList.get(0).getProductId());
                        data.put("value", BigDecimal.ONE);
                        phoneProductService.addStock(data);
                    }

                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 生成退款单
     * @param phoneOrder
     */
    public void insertRefunds(PhoneOrder phoneOrder){
        PhoneRefunds phoneRefunds = new PhoneRefunds();
        phoneRefunds.setCreateDate(new Date());
        phoneRefunds.setAmount(phoneOrder.getAmountPaid());
        phoneRefunds.setFee(BigDecimal.ZERO);
        phoneRefunds.setExpire(DateUtils.addMinutes(new Date(),30));
        phoneRefunds.setMemo("退款-"+phoneOrder.getTitle());
        phoneRefunds.setMethod(Refunds.METHOD_ONLINE);
        phoneRefunds.setSn(sysSequenceService.generate("phoneRefunds"));
        phoneRefunds.setStatus(Refunds.STATUS_WAITING);
        phoneRefunds.setType(Refunds.TYPE_ORDER);
        phoneRefunds.setMemberId(phoneOrder.getMemberId());
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("orderId", phoneOrder.getId());
        List<PhonePayment> phonePaymentList = phonePaymentService.selectList(params);
        if (0 < phonePaymentList.size()) {
            phoneRefunds.setPaymentId(phonePaymentList.get(0).getId());
            phoneRefunds.setPaymentPluginId(phonePaymentList.get(0).getPaymentPluginId());
            phoneRefunds.setPaymentPluginName(phonePaymentList.get(0).getPaymentPluginName());
        }
        phoneRefunds.setWay(1);
        phoneRefunds.setDeleted(false);
        phoneRefunds.setOrderId(phoneOrder.getId());
        phoneRefunds.setOrderSn(phoneOrder.getSn());
        Attach attach = new Attach();
        attach.setId(String.valueOf(phoneOrder.getId()));
        attach.setCode("9999");
        attach.setQueue("queue.phoneOrder.phoneRefunds");
        attach.setDescription(phoneOrder.getTitle());
        phoneRefunds.setAttach(JSON.toJSONString(attach));
        phoneRefunds.setEnterpriseId(phoneOrder.getEnterpriseId());
        phoneRefundsService.insertUseGeneratedKeys(phoneRefunds);

    }

    //退款成功回调
    @Transactional(rollbackFor = Exception.class)
    public void refundsHandle(Long id) {
        while (!redisHandler.lock("phoneOrder-phoneRefunds-".concat(String.valueOf(id)),String.valueOf(id))) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            PhoneOrder phoneOrder = super.findById(id);
            if (phoneOrder==null) {
                return;
            }
            if (phoneOrder.getOrderStatus().equals(PhoneOrderStatusEnum.ORDER_STATUS_COMPLETE.getId())) {
                return;
            }
            //更新订单状态及支付状态
            phoneOrder.setModifyDate(new Date());
            phoneOrder.setOrderStatus(PhoneOrderStatusEnum.ORDER_STATUS_CLOSE.getId());
            phoneOrder.setPaymentStatus(PhoneOrderStatusEnum.PAYMENT_STATUS_REFUND.getId());
            super.updateByPrimaryKey(phoneOrder);
            //更新支付记录的退款金额及退款日期
            Map<String, Object> param = new HashMap<String, Object>();
            param.put("orderId", id);
            List<PhonePayment> phonePaymentList = phonePaymentService.selectList(param);
            if (0 < phonePaymentList.size()) {
                PhonePayment phonePayment = phonePaymentList.get(0);
                phonePayment.setModifyDate(new Date());
                phonePayment.setRefund(phonePayment.getAmount());
                phonePaymentService.updateByPrimaryKey(phonePayment);
            }

            PhoneOrderLog phoneOrderLog = new PhoneOrderLog();
            phoneOrderLog.setType(PhoneOrderStatusEnum.ORDER_LOG_TYPE_REFUND.getId());
            phoneOrderLog.setContent("退款已完成");
            phoneOrderLog.setCreateDate(new Date());
            phoneOrderLog.setOrderId(phoneOrder.getId());
            phoneOrderLogService.insertUseGeneratedKeys(phoneOrderLog);

        } finally {
            redisHandler.unlock("phoneOrder-phoneRefunds-".concat(String.valueOf(id)),String.valueOf(id));
        }

    }

    //付款成功回调
    @Transactional(rollbackFor = Exception.class)
    public void paymentHandle(Long id) {

        while (!redisHandler.lock("phoneOrder-phonePayment-".concat(String.valueOf(id)),String.valueOf(id))) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        try {

            PhoneOrder phoneOrder = selectByPrimaryKey(id);
            if (phoneOrder==null) {
                return;
            }
            if (phoneOrder.getPaymentStatus().equals(PhoneOrderStatusEnum.PAYMENT_STATUS_PAY.getId())) {
                return;
            }

            //只用于第三方支付或钱包余额支付,付清剩余所有款项
            phoneOrder.setModifyDate(new Date());
            phoneOrder.setAmountPaid(phoneOrder.getAmountPayable());
            phoneOrder.setPaymentStatus(PhoneOrderStatusEnum.PAYMENT_STATUS_PAY.getId());
            phoneOrder.setOrderStatus(PhoneOrderStatusEnum.ORDER_STATUS_CONFIRM.getId());
            phoneOrderMapper.updateByPrimaryKeySelective(phoneOrder);

            PhoneOrderLog phoneOrderLog = new PhoneOrderLog();
            phoneOrderLog.setType(PhoneOrderStatusEnum.ORDER_LOG_TYPE_PAYEMNT.getId());
            phoneOrderLog.setContent("订单已付款");
            phoneOrderLog.setCreateDate(new Date());
            phoneOrderLog.setOrderId(phoneOrder.getId());
            phoneOrderLogService.insertUseGeneratedKeys(phoneOrderLog);

            phoneOrder.setItemList(phoneOrderItemService.getItemList(id));

            try {
                /*Member member = memberService.selectByPrimaryKey(phoneOrder.getMemberId());

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                DecimalFormat df = new DecimalFormat("0.00");
                SysUser sysUser = sysUserService.findById(member.getUserId());
                if (sysUser.getWxmId() != null) {
                    msgService.sendMiniOrderMsg(sysUser, sdf.format(new Date()), "您已成功下单", phoneOrder.getTitle(), phoneOrder.getSn(), df.format(phoneOrder.getAmountPayable()), "点击查看订单详情");
                }
                if (sysUser.getWxId() != null) {
                    msgService.sendMPOrderMsg(sysUser, sdf.format(new Date()), "您已成功下单", phoneOrder.getTitle(), phoneOrder.getSn(), df.format(phoneOrder.getAmountPayable()), "点击查看订单详情");
                }*/
                //调用豆讯话费充值功能
                //获取商品
                Enterprise enterprise = enterpriseService.findById(phoneOrder.getEnterpriseId());
                SysPlugin sysplugin = sysPluginService.findByPlugin(enterprise.getMchId(), "dxPhonePlugin");
                dxPhonePlugin.setPlugin(sysplugin, enterprise.getMchId());
                Map<String, Object> param = new HashMap<String, Object>();
                //订单号
                param.put("orderId", phoneOrder.getSn());
                List<Map<String, Object>> orderMapList = new ArrayList<Map<String, Object>>();
                Map<String, Object> orderParam = new HashMap<String, Object>();
                List<PhoneOrderItem> phoneOrderItemList = phoneOrderItemService.getItemList(phoneOrder.getId());
                //话费产品包
                orderParam.put("packCode", phoneOrderItemList.get(0).getSn());
                orderParam.put("mobile", phoneOrderItemList.get(0).getRechargeMobile());
                //立即生效
                orderParam.put("effectType", 1);
                orderMapList.add(orderParam);
                param.put("info", orderMapList);
                dxPhonePlugin.payPhoneBill(sysplugin, param);
            } catch (Exception e) {
                log.error(e.getMessage());
            }

        } finally {
            redisHandler.unlock("phoneOrder-phonePayment-".concat(String.valueOf(id)),String.valueOf(id));
        }

    }

    /**
     * 取消订单
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void cancel(Long id) {

        //1、检查销售订单是否存在
        PhoneOrder phoneOrder = selectByPrimaryKey(id);
        if (null == phoneOrder){
            throw new CustomException("未查找到订单");
        }

        if (phoneOrder.getOrderStatus().compareTo(PhoneOrderStatusEnum.ORDER_STATUS_CANCLE.getId())==0) {
            throw new CustomException("订单已关闭");
        }

        List<PhoneOrderItem> phoneOrderItemList = phoneOrderItemService.getItemList(id);
        phoneOrder.setItemList(phoneOrderItemList);
        //商品库存+1
        Map<String,Object> data = new HashMap<>();
        if (0 < phoneOrderItemList.size()) {
            data.put("id", phoneOrderItemList.get(0).getProductId());
            data.put("value", BigDecimal.ONE);
            phoneProductService.addStock(data);
        }
        phoneOrder.setOrderStatus(PhoneOrderStatusEnum.ORDER_STATUS_CANCLE.getId());

        super.updateByPrimaryKeySelective(phoneOrder);

        PhoneOrderLog phoneOrderLog = new PhoneOrderLog();
        phoneOrderLog.setType(PhoneOrderStatusEnum.ORDER_LOG_TYPE_CANCEL.getId());
        phoneOrderLog.setContent("订单已关闭");
        phoneOrderLog.setCreateDate(new Date());
        phoneOrderLog.setOrderId(phoneOrder.getId());
        phoneOrderLogService.insertUseGeneratedKeys(phoneOrderLog);

        try {
            Member member = memberService.selectByPrimaryKey(phoneOrder.getMemberId());

            member.setAmount(member.getAmount().subtract(phoneOrder.getAmountPayable()));
            memberService.updateByPrimaryKeySelective(member);

            Map<String,Object> content = new HashMap<>();
            content.put("title","您的订单已关闭");
            content.put("itemList",phoneOrder.getItemList());
            content.put("sn",phoneOrder.getSn());
            content.put("id",phoneOrder.getId());
            msgService.sendNotity(member,"msg-order","您的订单已关闭",JSON.toJSONString(content),null);

        } catch (Exception e) {
            log.error(e.getMessage());
        }

    }
}
